package com.mcxx.modules.report.service;

import com.google.common.base.Strings;
import com.mcxx.common.StatisDataItemEntityBuilder;
import com.mcxx.modules.statistics.dao.read.StatisDataItemReadDao;
import com.mcxx.modules.statistics.entity.StatisDataItemEntity;
import com.mcxx.modules.statistics.entity.StatisItemEntity;
import com.mcxx.util.AreaUtil;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
import com.yinhai.ta404.component.org.orguser.area.entity.TaAreaPo;
import com.yinhai.ta404.core.service.BaseService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;


public abstract class StatisDataService  extends BaseService {
    private final static org.slf4j.Logger logger = LoggerFactory.getLogger(StatisDataService.class);
    @Autowired
    protected AreaUtil areaUtil;
    @Autowired
    protected StatisDataItemReadDao statisDataItemReadDao;

    abstract public String getAccumulativeGoalCode(String basicCode);

    
    public void generateItemReport(TaAreaPo curTaAreaPo, String month, String itemSetId,
                                   StatisItemEntity item){

        String statisticSql = item.getSqlExpress();
        String[] params = item.getStatisParamNum().split(",");
        for (String param : params) {
            if (param.equals(Constant.Parameter.LEVEL)) {
                statisticSql = statisticSql.replace(param, String.valueOf(curTaAreaPo.getAreaLevel()));
            }
            if (param.equals(Constant.Parameter.TIME)) {
                statisticSql = statisticSql.replace(param,
                        "'" + month.substring(0, 4) + "-" + month.substring(4, 6) + "-01'");
            }
            if (param.equals(Constant.Parameter.AREA)) {
                statisticSql = statisticSql.replace(param, "'" +
                        areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()) + "'");
            }
            if (param.equals(Constant.Parameter.MONTH)) {
                statisticSql = statisticSql.replace(param, "'" + month + "'");
            }
        }

        logger.info("执行指标，name:{}, code:{}", item.getStatisItemName(), item.getStatisItemCode());
        statisticSql = statisticSql.replace("\n", " ");

        List<StatisDataItemEntity> paList = statisDataItemReadDao.queryStatisItem(statisticSql);


        paList.removeAll(Collections.singletonList(null));
        logger.info("查询到{}条数据", paList.size());

        Map<String, StatisDataItemEntity> mapSuperLevelSummary = new HashMap<String, StatisDataItemEntity>();
        for(StatisDataItemEntity record: paList){
            if(CommonUtil.invalidArgs(record.getAreaCode())){
                continue;
            }


            int curLevel = areaUtil.getLevelByAreaCode(record.getAreaCode());

            StatisDataItemEntityBuilder builder = new StatisDataItemEntityBuilder(record);
            builder.init(record.getAreaCode(), curLevel,  month, itemSetId);
            builder.setStatisItem(item);


            for(int level = curLevel - 1;  level >= Constant.AreaLevel.PROVINCE; level--){
                String superAreaCode = getSuperLevelAreaCodeOverWrite(record.getAreaCode(), level);
//                        areaUtil.getSuperLevelAreaCode(record.getAreaCode(), level);
                if(null == mapSuperLevelSummary.get(superAreaCode)){
                    builder = new StatisDataItemEntityBuilder(new StatisDataItemEntity());
                    builder.init(superAreaCode, null, month, itemSetId);
                    builder.setStatisItem(item);
                    builder.setData(record);
                    mapSuperLevelSummary.put(superAreaCode, builder.get());
                }
                else{
                    StatisDataItemEntity superStatisDataItem = mapSuperLevelSummary.get(superAreaCode);
                    superStatisDataItem.add(record);
                }
            }
        }


        clearAndUpdate(mapSuperLevelSummary, paList, curTaAreaPo, month, item.getBusinessType(),
                item.getStatisItemCode(), item.getExceptionalPovertyType());
    }

    
    public void generateAccumulativeReport(TaAreaPo curTaAreaPo, String month, String itemSetId,
                                                    StatisItemEntity item){
        String areaCode = areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel());
        String firstMonth = month.substring(0, 4) + "01";
        String accumulativeGoalCode = this.getAccumulativeGoalCode(item.getStatisItemCode());


        List<StatisDataItemEntity> statisDatas = statisDataItemReadDao.getStatisAccumulative(item.getBusinessType(),
                item.getStatisItemCode(), month, firstMonth, areaCode, item.getExceptionalPovertyType());

        StatisDataItemEntityBuilder builder = new StatisDataItemEntityBuilder();
        Map<String, StatisDataItemEntity> mapSuperLevelSummary = new HashMap<String, StatisDataItemEntity>();
        for(StatisDataItemEntity record : statisDatas){

            builder.setStatisItemEntity(record);
            builder.init(record.getAreaCode(), areaUtil.getLevelByAreaCode(record.getAreaCode()), month, itemSetId);
            builder.setStatisItem(item);
            builder.get().setStatisConfigCode(accumulativeGoalCode);
            builder.get().setStatisConfigName("1-当月累计"+item.getStatisItemName());


            for(int level = Constant.AreaLevel.COMMUNITY - 1;  level >= Constant.AreaLevel.PROVINCE; level--){
                String superAreaCode = getSuperLevelAreaCodeOverWrite(record.getAreaCode(), level);
//                        areaUtil.getSuperLevelAreaCode(record.getAreaCode(), level);
                if(null == mapSuperLevelSummary.get(superAreaCode)){
                    builder.setStatisItemEntity(new StatisDataItemEntity());
                    builder.init(superAreaCode, null, month, itemSetId);
                    builder.setStatisItem(item);
                    builder.get().setStatisConfigCode(accumulativeGoalCode);
                    builder.get().setStatisConfigName("1-当月累计"+item.getStatisItemName());
                    builder.setData(record);
                    mapSuperLevelSummary.put(superAreaCode, builder.get());
                }
                else{
                    StatisDataItemEntity superStatisDataItem = mapSuperLevelSummary.get(superAreaCode);
                    superStatisDataItem.add(record);
                }
            }
        }


        clearAndUpdate(mapSuperLevelSummary, statisDatas, curTaAreaPo, month, item.getBusinessType(),
                        accumulativeGoalCode, item.getExceptionalPovertyType());
    }

    
    public void clearAndUpdate(Map<String, StatisDataItemEntity> mapSuperLevelSummary, List<StatisDataItemEntity> coList,
                               TaAreaPo curTaAreaPo, String month, String businessType, String statisConfigCode,
                               String povertyType){


        List<String> areaCodes = areaUtil.getNodeTreePathFromRoot(curTaAreaPo.getAreaCode());
        List<StatisDataItemEntity> superAreaStatis = statisDataItemReadDao.getStatistics(areaCodes, month,
                                                                        businessType, statisConfigCode, povertyType);

        if(superAreaStatis.size() > 0){

            Optional<StatisDataItemEntity> curStatistic =
                    superAreaStatis.stream().filter(
                            statistic -> statistic.getAreaCode().equals(curTaAreaPo.getAreaCode())).findFirst();

            if(curStatistic.isPresent()){
                for(StatisDataItemEntity statistic : superAreaStatis) {
                    if(!statistic.getAreaCode().equals(curTaAreaPo.getAreaCode())){

                        statistic.sub(curStatistic.get());

                        StatisDataItemEntity curData = mapSuperLevelSummary.get(curTaAreaPo.getAreaCode());
                        if(null != curData)
                            statistic.add(curData);
                        statisDataItemReadDao.updateStatistic(statistic);
                        mapSuperLevelSummary.remove(statistic.getAreaCode());
                    }
                }
            } else {

                StatisDataItemEntity curGenerate = mapSuperLevelSummary.get(curTaAreaPo.getAreaCode());
                if (null != curGenerate) {
                    for(StatisDataItemEntity statistic : superAreaStatis) {
                        if(!statistic.getAreaCode().equals(curTaAreaPo.getAreaCode())){

                            statistic.add(curGenerate);
                            statisDataItemReadDao.updateStatistic(statistic);
                            mapSuperLevelSummary.remove(statistic.getAreaCode());
                        }
                    }
                }
            }
        }


        statisDataItemReadDao.delSonAreaStatistics(
                areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()),
                month, businessType, statisConfigCode, povertyType);

        List<StatisDataItemEntity> listSummary = new ArrayList<>(mapSuperLevelSummary.values());
        logger.info("写入非社区级数据：{}条", listSummary.size());
        List<List<StatisDataItemEntity>> lists = new ArrayList<List<StatisDataItemEntity>>();
        if(listSummary.size() > 0)
            lists.addAll(CommonUtil.fixedGrouping(listSummary, 100));

        if(coList.size() > 0)
            lists.addAll(CommonUtil.fixedGrouping(coList, 100));
        logger.info("写入社区级数据：{}条", coList.size());
        for(List<StatisDataItemEntity> temps : lists)
            statisDataItemReadDao.addStatistics(temps);
    }


    
    public String getSuperLevelAreaCodeOverWrite(String areaCode, int level){
        String selfArea = areaCode.substring(4, 9);
        switch (level){
            case Constant.AreaLevel.PROVINCE:
                return areaCode.substring(0, 2) + "0000000000";
            case Constant.AreaLevel.CITY:
                return areaCode.substring(0, 4) + "00000000";
            case Constant.AreaLevel.COUNTY:
                if("00999".equals(selfArea)) {
                    return areaCode.substring(0, 6) + "999000";
                }
                return areaCode.substring(0, 6) + "000000";
            case Constant.AreaLevel.STREET:
                if("00999".equals(selfArea)) {

                    String superCode = statisDataItemReadDao.getSuperLevelByAreaCode(areaCode);
                    if (Strings.isNullOrEmpty(superCode)) {
                        logger.info("{},地区未找到对应的父级编码", areaCode);
                        return areaCode.substring(0, 9) + "000";

                    }
                    return superCode;
                }
                return areaCode.substring(0, 9) + "000";
            case Constant.AreaLevel.COMMUNITY:
                return areaCode.substring(0, 12);
            default:
                return areaCode;
        }
    }
}
